bitkeeper revision 1.777 (404f4cb5WovysmMe80HYkFhXdVbs9A)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 10 Mar 2004 17:13:25 +0000 (17:13 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 10 Mar 2004 17:13:25 +0000 (17:13 +0000)
Rules.mk, Makefile:
  Xen uses TARGET_ARCH instead of ARCH for clarity and to prevent conflict with other uses of ARCH in the environment.
xend_utils.c:
  Rename: tools/xend/xend.c -> tools/xend/xend_utils.c

.rootkeys
tools/xend/xend.c [deleted file]
tools/xend/xend_utils.c [new file with mode: 0644]
xen/Makefile
xen/Rules.mk

index 0dfb9f395c5dac296f094270514767977666d703..3458df6fc66286ef429e15d244cf6351480ee3f4 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
@@ -88,7 +88,7 @@
 3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xc/py/XenoUtil.py
 3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
 40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
-40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/xend.c
+40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/xend_utils.c
 403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
 403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
 403a3edb0lzD0Fojc-NYNoXr3SYrnA tools/xentrace/xentrace_cpusplit.py
diff --git a/tools/xend/xend.c b/tools/xend/xend.c
deleted file mode 100644 (file)
index ef6e903..0000000
+++ /dev/null
@@ -1,616 +0,0 @@
-/******************************************************************************
- * xend.c
- * 
- * The grand Xen daemon. For now it's just a virtual-console concentrator.
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <xc.h>
-#include <asm-xeno/control_if.h>
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 200
-#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
-#define PORT_DISCONNECT 0x8000   /* A port-disconnect notification.     */
-#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
-#define EVTCHN_RESET _IO('E', 1) /* Clear notification buffer. Clear errors. */
-
-/* Error macros. */
-#define ERROR(_f, _a...)     \
-    fprintf ( stderr, "ERROR: " _f "\n" , ## _a );
-#define SYS_ERROR(_f, _a...) \
-    fprintf ( stderr, "ERROR: " _f " [errno=%d (%s)]\n" , \
-              ## _a , errno , strerror(errno) );
-#define HINT(_f, _a...)      \
-    fprintf ( stderr, "Hint: " _f "\n" , ## _a );
-#define ROOT_HINT() HINT("You must execute this daemon as root.")
-#define DOM0_HINT() HINT("You must execute this daemon " \
-                         "on a privileged Xenolinux instance (e.g., DOM0).")
-
-#if 0
-#define DPRINTF(_f, _a...)  \
-    fprintf ( stdout, _f "\n" , ## _a );
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
-
-/* Per-port Tx/Rx buffering. */
-#define CONBUFSZ 65536
-#define MASK_CONBUF_IDX(_i) ((_i)&(CONBUFSZ-1))
-
-struct portinfo;
-typedef struct portinfo {
-    u64              dom;
-    control_if_t    *interface;
-    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
-    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
-    char            *tx_buf, *rx_buf;
-    unsigned int     txp, txc, rxp, rxc;
-#define CONSTAT_CLOSED    0
-#define CONSTAT_LISTENING 1
-#define CONSTAT_CONNECTED 2
-    int              con_fd, con_status;
-    struct portinfo **pprev, *next; /* links to other active ports */
-} portinfo_t;
-
-#define PORT(_pinfo) ((_pinfo)-portinfo)
-#define TX_EMPTY(_pinfo) ((_pinfo)->txp == (_pinfo)->txc)
-#define TX_FULL(_pinfo)  (((_pinfo)->txp - (_pinfo)->txc) == CONBUFSZ)
-#define RX_EMPTY(_pinfo) ((_pinfo)->rxp == (_pinfo)->rxc)
-#define RX_FULL(_pinfo)  (((_pinfo)->rxp - (_pinfo)->rxc) == CONBUFSZ)
-
-static portinfo_t *active_head;   /* linked list of active ports */
-static portinfo_t portinfo[1024]; /* array of all ports */    
-static int xc_fd, evt_fd, mem_fd;
-
-#define PAGE_SIZE           4096 /* size of a machine page frame            */
-#define BATCH_SIZE           512 /* maximum notifications to read at a time */
-
-static int make_consock_listener(portinfo_t *pinfo);
-static int make_consock_connected(portinfo_t *pinfo);
-static void make_consock_closed(portinfo_t *pinfo);
-static void do_consock_read(portinfo_t *pinfo);
-static void do_consock_write(portinfo_t *pinfo);
-static int process_evtchn_reads(portinfo_t *pinfo);
-static int process_evtchn_writes(portinfo_t *pinfo);
-
-static control_if_t *map_control_interface(int fd, unsigned long pfn)
-{
-    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
-                       MAP_SHARED, fd, pfn * PAGE_SIZE);
-    if ( vaddr == MAP_FAILED )
-        return NULL;
-    return (control_if_t *)(vaddr + 2048);
-}
-
-static void unmap_control_interface(int fd, control_if_t *c)
-{
-    char *vaddr = (char *)c - 2048;
-    (void)munmap(vaddr, PAGE_SIZE);
-}
-
-/* Returns TRUE if the channel is open on exit. */
-static int handle_channel_exception(unsigned int port)
-{
-    xc_dominfo_t info;
-    unsigned int remote_port, status;
-    u64          remote_dom;
-    u16          wbuf;
-    portinfo_t  *pinfo = &portinfo[port];
-
-    if ( xc_evtchn_status(xc_fd, DOMID_SELF, port, 
-                          &remote_dom, &remote_port, &status) != 0 )
-    {
-        SYS_ERROR("Unexpected failure when obtaining port-%d status.", port);
-        exit(1);
-    }
-    
-    if ( status != EVTCHNSTAT_connected )
-    {
-        DPRINTF("Port %d not connected: cleaning up.", port);
-        if ( pinfo->interface != NULL )
-        {
-            unmap_control_interface(mem_fd, pinfo->interface);
-            pinfo->interface = NULL;
-            *(pinfo->pprev) = pinfo->next;
-            if ( pinfo->next != NULL )
-                pinfo->next->pprev = pinfo->pprev;
-            make_consock_closed(pinfo);
-            free(pinfo->tx_buf);
-            free(pinfo->rx_buf);
-            memset(pinfo, 0, sizeof(*pinfo));
-        }
-        /* Cleanup sanity: we'll be the grim reaper. */
-        wbuf = port | PORT_NORMAL;
-        (void)write(evt_fd, &wbuf, sizeof(wbuf));
-        wbuf = port | PORT_DISCONNECT;
-        (void)write(evt_fd, &wbuf, sizeof(wbuf));
-        if ( status == EVTCHNSTAT_disconnected )
-            (void)xc_evtchn_close(xc_fd, DOMID_SELF, port);
-        return 0;
-    }
-
-    /* We only deal with initial ports (id == 0). */
-    if ( remote_port != 0 )
-        return 0;
-
-    if ( pinfo->interface == NULL )
-    {
-        DPRINTF("New control interface for DOM%llu on port %d.", 
-                remote_dom, port);
-        if ( xc_domain_getinfo(xc_fd, remote_dom, 1, &info) != 1 )
-        {
-            SYS_ERROR("Failed to obtain DOM%llu status.", remote_dom);
-            exit(1);
-        }
-        memset(pinfo, 0, sizeof(*pinfo));
-        pinfo->interface = 
-            map_control_interface(mem_fd, info.shared_info_frame);
-        pinfo->tx_buf = malloc(CONBUFSZ);
-        pinfo->rx_buf = malloc(CONBUFSZ);
-        pinfo->dom = remote_dom;
-        pinfo->con_status = CONSTAT_CLOSED;
-        if ( !make_consock_listener(pinfo) )
-        {
-            ERROR("Could not start console %d in listener status.",
-                  PORT(pinfo));
-            exit(1);
-        }
-        pinfo->pprev = &active_head;
-        if ( (pinfo->next = active_head) != NULL )
-            pinfo->next->pprev = &pinfo->next;
-        active_head = pinfo;
-    }
-
-    return 1;
-}
-
-static void process_channel(unsigned int port)
-{
-    portinfo_t      *pinfo = &portinfo[port];
-    u16              wbuf = port;
-
-    /* Acknowledge the notification. */
-    (void)write(evt_fd, &wbuf, sizeof(wbuf));
-
-    /* Process requests; send notification if we updated either ring. */
-    if ( process_evtchn_reads(pinfo) || process_evtchn_writes(pinfo) )
-        (void)xc_evtchn_send(xc_fd, port);
-}
-
-int main(int argc, char **argv)
-{
-    struct pollfd polls[1025]; /* one per port, plus /dev/xeno/evtchn */
-    portinfo_t *pinfo;
-    unsigned int batch, bytes, i, port, fd_idx;
-    u16 buf[BATCH_SIZE];
-
-    /* Ignore writes to disconnected sockets. We clear up later. */
-    (void)signal(SIGPIPE, SIG_IGN);
-    
-    if ( (evt_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR)) == -1 )
-    {
-        SYS_ERROR("Could not open '%s'", EVTCHN_DEV_NAME);
-        ROOT_HINT();
-        HINT("On a non-devfs system you must run 'mknod %s c %d %d'.",
-             EVTCHN_DEV_NAME, EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR);
-        exit(1);
-    }
-
-    if ( (mem_fd = open("/dev/mem", O_RDWR)) == -1 )
-    {
-        SYS_ERROR("Could not open '/dev/mem'");
-        ROOT_HINT();
-        exit(1);
-    }
-
-    if ( (xc_fd = xc_interface_open()) == -1 )
-    {
-        SYS_ERROR("Could not open Xen control interface");
-        ROOT_HINT();
-        DOM0_HINT();
-        exit(1);
-    }
-
-    for ( ; ; )
-    {
-        polls[0].fd     = evt_fd;
-        polls[0].events = POLLIN;
-
-        fd_idx = 1;
-        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
-        {
-            switch ( pinfo->con_status )
-            {
-            case CONSTAT_LISTENING:
-                polls[fd_idx].fd     = pinfo->con_fd;
-                polls[fd_idx].events = POLLIN;
-                fd_idx++;
-                break;
-            case CONSTAT_CONNECTED:
-                polls[fd_idx].fd     = pinfo->con_fd;
-                polls[fd_idx].events = POLLIN | (RX_EMPTY(pinfo)?0:POLLOUT);
-                fd_idx++;
-                break;
-            }
-        }
-
-        while ( poll(polls, fd_idx, -1) == -1 )
-        {
-            if ( errno == EINTR )
-                continue;
-            SYS_ERROR("Unexpected error from poll().");
-            exit(1);
-        }
-
-        fd_idx = 1;
-        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
-        {
-            switch ( pinfo->con_status )
-            {
-            case CONSTAT_LISTENING:
-                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
-                    (void)make_consock_connected(pinfo);
-                break;
-            case CONSTAT_CONNECTED:
-                if ( ((polls[fd_idx].revents & POLLOUT) != 0) )
-                    do_consock_write(pinfo);
-                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
-                    do_consock_read(pinfo);
-                break;
-            }
-            fd_idx++;
-        }
-
-        while ( (bytes = read(evt_fd, buf, sizeof(buf))) == -1 )
-        {
-            if ( errno == EINTR )
-                continue;
-            if ( errno == EAGAIN )
-            {
-                bytes = 0;
-                break;
-            }
-            SYS_ERROR("Unexpected error while reading '%s'.", EVTCHN_DEV_NAME);
-            exit(1);
-        }
-        
-        if ( bytes == 0 )
-            continue;
-
-        if ( (bytes & 1) != 0 )
-        {
-            ERROR("Bad read length (%d bytes) from '%s'.",
-                  bytes, EVTCHN_DEV_NAME);
-            exit(1);
-        }
-        
-        batch = bytes / sizeof(u16);
-        for ( i = 0; i < batch; i++ )
-        {
-            port = buf[i] & PORTIDX_MASK;
-            
-            if ( buf[i] & PORT_DISCONNECT )
-            {
-                DPRINTF("Disconnect on port %d.", port);
-                (void)handle_channel_exception(port);
-                continue;
-            }
-            
-            if ( portinfo[port].interface == NULL )
-            {
-                DPRINTF("Unexpected notification on port %d.", port);
-                if ( !handle_channel_exception(port) )
-                    continue;
-            }
-            
-            process_channel(port);
-        }
-    }
-
-    (void)xc_interface_close(xc_fd);
-    (void)close(mem_fd);
-    (void)close(evt_fd);
-
-    return 0;
-}
-
-
-/* Returns non-zero if console is listening on exit. */
-static int make_consock_listener(portinfo_t *pinfo)
-{
-    int reuseaddr_flag = 1;
-    struct linger linger;
-    int tcp_port = 9600 + PORT(pinfo);
-    int fd, flags;
-    struct sockaddr_in sa;
-
-    if ( pinfo->con_status == CONSTAT_LISTENING )
-        return 1;
-
-    if ( pinfo->con_status == CONSTAT_CONNECTED )
-    {
-        (void)close(pinfo->con_fd);
-        pinfo->con_status = CONSTAT_CLOSED;
-    }
-
-    if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
-    {
-        SYS_ERROR("Could not create TCP socket.");
-        return 0;
-    }
-
-    linger.l_onoff = 0;
-    if ( (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
-                     &reuseaddr_flag, sizeof(int)) != 0) ||
-         (setsockopt(fd, SOL_SOCKET, SO_LINGER, 
-                     &linger, sizeof(linger)) != 0) )
-    {
-        SYS_ERROR("Could not enable immediate reuse of socket port.");
-        close(fd);
-        return 0;
-    }
-
-    sa.sin_family      = AF_INET;
-    sa.sin_addr.s_addr = htonl(INADDR_ANY);
-    sa.sin_port        = htons(tcp_port);
-    if ( bind(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 )
-    {
-        SYS_ERROR("Unable to bind to console port %d.", tcp_port);
-        close(fd);
-        return 0;
-    }
-
-    if ( listen(fd, 5) != 0 )
-    {
-        SYS_ERROR("Unable to listen on console port %d.", tcp_port);
-        close(fd);
-        return 0;
-    }
-
-    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
-         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
-    {
-        SYS_ERROR("Unable to set non-blocking status for console listener.");
-        close(fd);
-        return 0;
-    }
-
-    pinfo->con_fd     = fd;
-    pinfo->con_status = CONSTAT_LISTENING;
-    return 1;
-}
-
-/* Returns non-zero if console is connected on exit. */
-static int make_consock_connected(portinfo_t *pinfo)
-{
-    int fd, flags, sa_len;
-    struct linger linger;
-    struct sockaddr_in sa;
-
-    if ( pinfo->con_status == CONSTAT_CONNECTED )
-        return 1;
-
-    if ( pinfo->con_status == CONSTAT_CLOSED )
-        return 0;
-
-    if ( (fd = accept(pinfo->con_fd, (struct sockaddr *)&sa, &sa_len)) == -1 )
-        return 0;
-
-    linger.l_onoff = 0;
-    if ( setsockopt(fd, SOL_SOCKET, SO_LINGER, 
-                    &linger, sizeof(linger)) != 0 )
-    {
-        SYS_ERROR("Could not enable immediate socket death.");
-        close(fd);
-        return 0;
-    }
-
-    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
-         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
-    {
-        SYS_ERROR("Unable to set non-blocking status on socket.");
-        close(fd);
-        return 0;
-    }
-
-    (void)close(pinfo->con_fd);
-
-    pinfo->con_fd     = fd;
-    pinfo->con_status = CONSTAT_CONNECTED;
-    return 1;
-}
-
-
-static void make_consock_closed(portinfo_t *pinfo)
-{
-    if ( pinfo->con_status != CONSTAT_CLOSED )
-        (void)close(pinfo->con_fd);
-    pinfo->con_status = CONSTAT_CLOSED;
-}
-
-
-static void do_consock_read(portinfo_t *pinfo)
-{
-    char buf[1024];
-    int  idx, bytes, rc, was_empty = TX_EMPTY(pinfo);
-
-    while ( (rc = read(pinfo->con_fd, &buf, sizeof(buf))) > 0 )
-    {
-        idx = 0;
-        while ( (rc != 0) && !TX_FULL(pinfo) )
-        {
-            bytes = rc;
-            /* Clip copy to ring-buffer wrap. */
-            if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp)) )
-                bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp);
-            /* Clip copy to ring-buffer overflow. */
-            if ( bytes > (CONBUFSZ - (pinfo->txp - pinfo->txc)) )
-                bytes = CONBUFSZ - (pinfo->txp - pinfo->txc);
-            memcpy(&pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txp)],
-                   &buf[idx], bytes);
-            pinfo->txp += bytes;
-            idx        += bytes;
-            rc         -= bytes;
-        }
-    }
-
-    if ( (rc == 0) || (errno != EAGAIN) )
-    {
-        DPRINTF("Console client has disconnected.");
-        if ( !make_consock_listener(pinfo) )
-        {
-            ERROR("Could not revert console %d to listener status.",
-                  PORT(pinfo));
-            exit(1);
-        }
-    }
-
-    if ( was_empty && !TX_EMPTY(pinfo) )
-    {
-        /* There is now data to transmit to guest. Kickstart the pipeline. */
-        if ( process_evtchn_writes(pinfo) )
-            (void)xc_evtchn_send(xc_fd, PORT(pinfo));
-    }
-}
-
-static void do_consock_write(portinfo_t *pinfo)
-{
-    int bytes, rc;
-
-    while ( !RX_EMPTY(pinfo) )
-    {
-        /* Clip transfer to ring-buffer wrap. */
-        bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxc);
-        /* Clip transfer to ring-buffer overflow. */
-        if ( bytes > (pinfo->rxp - pinfo->rxc) )
-            bytes = pinfo->rxp - pinfo->rxc;
-        rc = write(pinfo->con_fd, 
-                   &pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxc)], 
-                   bytes);
-        if ( rc <= 0 )
-            return; /* Nothing to do. Errors cleaned up in reader code. */
-        pinfo->rxc += rc;
-    }
-}
-
-static int process_evtchn_reads(portinfo_t *pinfo)
-{
-    CONTROL_RING_IDX c;
-    control_if_t    *cif = pinfo->interface;
-    control_msg_t   *cmsg;
-    unsigned int     clen, idx, len, bytes;
-
-    for ( c = pinfo->tx_req_cons; 
-          (c != cif->tx_req_prod) && 
-              ((c-pinfo->tx_resp_prod) != CONTROL_RING_SIZE);
-          c++ )
-    {
-        cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
-
-        if ( (clen = cmsg->length) > sizeof(cmsg->msg) )
-            clen = sizeof(cmsg->msg);
-
-        if ( (cmsg->cmd_type == CMD_CONSOLE) &&
-             (cmsg->cmd_subtype == CMD_CONSOLE_DATA) )
-        {
-            idx = 0;
-            len = cmsg->length;
-            while ( (len != 0) && !RX_FULL(pinfo) )
-            {
-                bytes = len;
-                /* Clip copy to ring-buffer wrap. */
-                if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp)) )
-                    bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp);
-                /* Clip copy to ring-buffer overflow. */
-                if ( bytes > (CONBUFSZ - (pinfo->rxp - pinfo->rxc)) )
-                    bytes = CONBUFSZ - (pinfo->rxp - pinfo->rxc);
-                memcpy(&pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxp)],
-                       &cmsg->msg[idx], bytes);
-                pinfo->rxp += bytes;
-                idx += bytes;
-                len -= bytes;
-            }
-        }
-
-        /* Prepare response. No payload; msg type and id same as request. */
-        cmsg->length = 0;
-    }
-
-    if ( c != pinfo->tx_req_cons )
-    {
-        /* Update private indexes. */
-        pinfo->tx_resp_prod = c;
-        pinfo->tx_req_cons  = c;
-        /* Queue responses and send a notification to the guest OS. */
-        cif->tx_resp_prod   = c;
-        return 1;
-    }
-
-    return 0;
-}
-
-static int process_evtchn_writes(portinfo_t *pinfo)
-{
-    CONTROL_RING_IDX p, rx_resp_prod;
-    control_if_t    *cif = pinfo->interface;
-    control_msg_t   *cmsg;
-    unsigned int     bytes;
-
-    /* Validate the rx-response producer, an dupdate our consumer if okay. */
-    rx_resp_prod = cif->rx_resp_prod;
-    if ( (pinfo->rx_resp_cons != rx_resp_prod) &&
-         ((pinfo->rx_req_prod - rx_resp_prod) <= CONTROL_RING_SIZE) &&
-         ((rx_resp_prod - pinfo->rx_resp_cons) <= CONTROL_RING_SIZE) )
-        pinfo->rx_resp_cons = cif->rx_resp_prod;
-
-    for ( p = pinfo->rx_req_prod;
-          (p-pinfo->rx_resp_cons) != CONTROL_RING_SIZE;
-          p++ )
-    {
-        if ( TX_EMPTY(pinfo) )
-            break;
-        cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
-        bytes = sizeof(cmsg->msg);
-        /* Clip transfer to ring-buffer wrap. */
-        if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc)) )
-            bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc);
-        /* Clip transfer to ring-buffer overflow. */
-        if ( bytes > (pinfo->txp - pinfo->txc) )
-            bytes = pinfo->txp - pinfo->txc;
-        cmsg->cmd_type    = CMD_CONSOLE;
-        cmsg->cmd_subtype = CMD_CONSOLE_DATA;
-        cmsg->id          = 0xaa;
-        cmsg->length      = bytes;
-        memcpy(&cmsg->msg[0], 
-               &pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txc)], 
-               bytes);
-        pinfo->txc += bytes;
-    }
-
-    if ( p != pinfo->rx_req_prod )
-    {
-        pinfo->rx_req_prod  = p;
-        cif->rx_req_prod    = p;
-        return 1;
-    }
-
-    return 0;
-}
diff --git a/tools/xend/xend_utils.c b/tools/xend/xend_utils.c
new file mode 100644 (file)
index 0000000..ef6e903
--- /dev/null
@@ -0,0 +1,616 @@
+/******************************************************************************
+ * xend.c
+ * 
+ * The grand Xen daemon. For now it's just a virtual-console concentrator.
+ * 
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <xc.h>
+#include <asm-xeno/control_if.h>
+
+/* NB. The following should be kept in sync with the kernel's evtchn driver. */
+#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 200
+#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
+#define PORT_DISCONNECT 0x8000   /* A port-disconnect notification.     */
+#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
+#define EVTCHN_RESET _IO('E', 1) /* Clear notification buffer. Clear errors. */
+
+/* Error macros. */
+#define ERROR(_f, _a...)     \
+    fprintf ( stderr, "ERROR: " _f "\n" , ## _a );
+#define SYS_ERROR(_f, _a...) \
+    fprintf ( stderr, "ERROR: " _f " [errno=%d (%s)]\n" , \
+              ## _a , errno , strerror(errno) );
+#define HINT(_f, _a...)      \
+    fprintf ( stderr, "Hint: " _f "\n" , ## _a );
+#define ROOT_HINT() HINT("You must execute this daemon as root.")
+#define DOM0_HINT() HINT("You must execute this daemon " \
+                         "on a privileged Xenolinux instance (e.g., DOM0).")
+
+#if 0
+#define DPRINTF(_f, _a...)  \
+    fprintf ( stdout, _f "\n" , ## _a );
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+/* Per-port Tx/Rx buffering. */
+#define CONBUFSZ 65536
+#define MASK_CONBUF_IDX(_i) ((_i)&(CONBUFSZ-1))
+
+struct portinfo;
+typedef struct portinfo {
+    u64              dom;
+    control_if_t    *interface;
+    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
+    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
+    char            *tx_buf, *rx_buf;
+    unsigned int     txp, txc, rxp, rxc;
+#define CONSTAT_CLOSED    0
+#define CONSTAT_LISTENING 1
+#define CONSTAT_CONNECTED 2
+    int              con_fd, con_status;
+    struct portinfo **pprev, *next; /* links to other active ports */
+} portinfo_t;
+
+#define PORT(_pinfo) ((_pinfo)-portinfo)
+#define TX_EMPTY(_pinfo) ((_pinfo)->txp == (_pinfo)->txc)
+#define TX_FULL(_pinfo)  (((_pinfo)->txp - (_pinfo)->txc) == CONBUFSZ)
+#define RX_EMPTY(_pinfo) ((_pinfo)->rxp == (_pinfo)->rxc)
+#define RX_FULL(_pinfo)  (((_pinfo)->rxp - (_pinfo)->rxc) == CONBUFSZ)
+
+static portinfo_t *active_head;   /* linked list of active ports */
+static portinfo_t portinfo[1024]; /* array of all ports */    
+static int xc_fd, evt_fd, mem_fd;
+
+#define PAGE_SIZE           4096 /* size of a machine page frame            */
+#define BATCH_SIZE           512 /* maximum notifications to read at a time */
+
+static int make_consock_listener(portinfo_t *pinfo);
+static int make_consock_connected(portinfo_t *pinfo);
+static void make_consock_closed(portinfo_t *pinfo);
+static void do_consock_read(portinfo_t *pinfo);
+static void do_consock_write(portinfo_t *pinfo);
+static int process_evtchn_reads(portinfo_t *pinfo);
+static int process_evtchn_writes(portinfo_t *pinfo);
+
+static control_if_t *map_control_interface(int fd, unsigned long pfn)
+{
+    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, fd, pfn * PAGE_SIZE);
+    if ( vaddr == MAP_FAILED )
+        return NULL;
+    return (control_if_t *)(vaddr + 2048);
+}
+
+static void unmap_control_interface(int fd, control_if_t *c)
+{
+    char *vaddr = (char *)c - 2048;
+    (void)munmap(vaddr, PAGE_SIZE);
+}
+
+/* Returns TRUE if the channel is open on exit. */
+static int handle_channel_exception(unsigned int port)
+{
+    xc_dominfo_t info;
+    unsigned int remote_port, status;
+    u64          remote_dom;
+    u16          wbuf;
+    portinfo_t  *pinfo = &portinfo[port];
+
+    if ( xc_evtchn_status(xc_fd, DOMID_SELF, port, 
+                          &remote_dom, &remote_port, &status) != 0 )
+    {
+        SYS_ERROR("Unexpected failure when obtaining port-%d status.", port);
+        exit(1);
+    }
+    
+    if ( status != EVTCHNSTAT_connected )
+    {
+        DPRINTF("Port %d not connected: cleaning up.", port);
+        if ( pinfo->interface != NULL )
+        {
+            unmap_control_interface(mem_fd, pinfo->interface);
+            pinfo->interface = NULL;
+            *(pinfo->pprev) = pinfo->next;
+            if ( pinfo->next != NULL )
+                pinfo->next->pprev = pinfo->pprev;
+            make_consock_closed(pinfo);
+            free(pinfo->tx_buf);
+            free(pinfo->rx_buf);
+            memset(pinfo, 0, sizeof(*pinfo));
+        }
+        /* Cleanup sanity: we'll be the grim reaper. */
+        wbuf = port | PORT_NORMAL;
+        (void)write(evt_fd, &wbuf, sizeof(wbuf));
+        wbuf = port | PORT_DISCONNECT;
+        (void)write(evt_fd, &wbuf, sizeof(wbuf));
+        if ( status == EVTCHNSTAT_disconnected )
+            (void)xc_evtchn_close(xc_fd, DOMID_SELF, port);
+        return 0;
+    }
+
+    /* We only deal with initial ports (id == 0). */
+    if ( remote_port != 0 )
+        return 0;
+
+    if ( pinfo->interface == NULL )
+    {
+        DPRINTF("New control interface for DOM%llu on port %d.", 
+                remote_dom, port);
+        if ( xc_domain_getinfo(xc_fd, remote_dom, 1, &info) != 1 )
+        {
+            SYS_ERROR("Failed to obtain DOM%llu status.", remote_dom);
+            exit(1);
+        }
+        memset(pinfo, 0, sizeof(*pinfo));
+        pinfo->interface = 
+            map_control_interface(mem_fd, info.shared_info_frame);
+        pinfo->tx_buf = malloc(CONBUFSZ);
+        pinfo->rx_buf = malloc(CONBUFSZ);
+        pinfo->dom = remote_dom;
+        pinfo->con_status = CONSTAT_CLOSED;
+        if ( !make_consock_listener(pinfo) )
+        {
+            ERROR("Could not start console %d in listener status.",
+                  PORT(pinfo));
+            exit(1);
+        }
+        pinfo->pprev = &active_head;
+        if ( (pinfo->next = active_head) != NULL )
+            pinfo->next->pprev = &pinfo->next;
+        active_head = pinfo;
+    }
+
+    return 1;
+}
+
+static void process_channel(unsigned int port)
+{
+    portinfo_t      *pinfo = &portinfo[port];
+    u16              wbuf = port;
+
+    /* Acknowledge the notification. */
+    (void)write(evt_fd, &wbuf, sizeof(wbuf));
+
+    /* Process requests; send notification if we updated either ring. */
+    if ( process_evtchn_reads(pinfo) || process_evtchn_writes(pinfo) )
+        (void)xc_evtchn_send(xc_fd, port);
+}
+
+int main(int argc, char **argv)
+{
+    struct pollfd polls[1025]; /* one per port, plus /dev/xeno/evtchn */
+    portinfo_t *pinfo;
+    unsigned int batch, bytes, i, port, fd_idx;
+    u16 buf[BATCH_SIZE];
+
+    /* Ignore writes to disconnected sockets. We clear up later. */
+    (void)signal(SIGPIPE, SIG_IGN);
+    
+    if ( (evt_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR)) == -1 )
+    {
+        SYS_ERROR("Could not open '%s'", EVTCHN_DEV_NAME);
+        ROOT_HINT();
+        HINT("On a non-devfs system you must run 'mknod %s c %d %d'.",
+             EVTCHN_DEV_NAME, EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR);
+        exit(1);
+    }
+
+    if ( (mem_fd = open("/dev/mem", O_RDWR)) == -1 )
+    {
+        SYS_ERROR("Could not open '/dev/mem'");
+        ROOT_HINT();
+        exit(1);
+    }
+
+    if ( (xc_fd = xc_interface_open()) == -1 )
+    {
+        SYS_ERROR("Could not open Xen control interface");
+        ROOT_HINT();
+        DOM0_HINT();
+        exit(1);
+    }
+
+    for ( ; ; )
+    {
+        polls[0].fd     = evt_fd;
+        polls[0].events = POLLIN;
+
+        fd_idx = 1;
+        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
+        {
+            switch ( pinfo->con_status )
+            {
+            case CONSTAT_LISTENING:
+                polls[fd_idx].fd     = pinfo->con_fd;
+                polls[fd_idx].events = POLLIN;
+                fd_idx++;
+                break;
+            case CONSTAT_CONNECTED:
+                polls[fd_idx].fd     = pinfo->con_fd;
+                polls[fd_idx].events = POLLIN | (RX_EMPTY(pinfo)?0:POLLOUT);
+                fd_idx++;
+                break;
+            }
+        }
+
+        while ( poll(polls, fd_idx, -1) == -1 )
+        {
+            if ( errno == EINTR )
+                continue;
+            SYS_ERROR("Unexpected error from poll().");
+            exit(1);
+        }
+
+        fd_idx = 1;
+        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
+        {
+            switch ( pinfo->con_status )
+            {
+            case CONSTAT_LISTENING:
+                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
+                    (void)make_consock_connected(pinfo);
+                break;
+            case CONSTAT_CONNECTED:
+                if ( ((polls[fd_idx].revents & POLLOUT) != 0) )
+                    do_consock_write(pinfo);
+                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
+                    do_consock_read(pinfo);
+                break;
+            }
+            fd_idx++;
+        }
+
+        while ( (bytes = read(evt_fd, buf, sizeof(buf))) == -1 )
+        {
+            if ( errno == EINTR )
+                continue;
+            if ( errno == EAGAIN )
+            {
+                bytes = 0;
+                break;
+            }
+            SYS_ERROR("Unexpected error while reading '%s'.", EVTCHN_DEV_NAME);
+            exit(1);
+        }
+        
+        if ( bytes == 0 )
+            continue;
+
+        if ( (bytes & 1) != 0 )
+        {
+            ERROR("Bad read length (%d bytes) from '%s'.",
+                  bytes, EVTCHN_DEV_NAME);
+            exit(1);
+        }
+        
+        batch = bytes / sizeof(u16);
+        for ( i = 0; i < batch; i++ )
+        {
+            port = buf[i] & PORTIDX_MASK;
+            
+            if ( buf[i] & PORT_DISCONNECT )
+            {
+                DPRINTF("Disconnect on port %d.", port);
+                (void)handle_channel_exception(port);
+                continue;
+            }
+            
+            if ( portinfo[port].interface == NULL )
+            {
+                DPRINTF("Unexpected notification on port %d.", port);
+                if ( !handle_channel_exception(port) )
+                    continue;
+            }
+            
+            process_channel(port);
+        }
+    }
+
+    (void)xc_interface_close(xc_fd);
+    (void)close(mem_fd);
+    (void)close(evt_fd);
+
+    return 0;
+}
+
+
+/* Returns non-zero if console is listening on exit. */
+static int make_consock_listener(portinfo_t *pinfo)
+{
+    int reuseaddr_flag = 1;
+    struct linger linger;
+    int tcp_port = 9600 + PORT(pinfo);
+    int fd, flags;
+    struct sockaddr_in sa;
+
+    if ( pinfo->con_status == CONSTAT_LISTENING )
+        return 1;
+
+    if ( pinfo->con_status == CONSTAT_CONNECTED )
+    {
+        (void)close(pinfo->con_fd);
+        pinfo->con_status = CONSTAT_CLOSED;
+    }
+
+    if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
+    {
+        SYS_ERROR("Could not create TCP socket.");
+        return 0;
+    }
+
+    linger.l_onoff = 0;
+    if ( (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
+                     &reuseaddr_flag, sizeof(int)) != 0) ||
+         (setsockopt(fd, SOL_SOCKET, SO_LINGER, 
+                     &linger, sizeof(linger)) != 0) )
+    {
+        SYS_ERROR("Could not enable immediate reuse of socket port.");
+        close(fd);
+        return 0;
+    }
+
+    sa.sin_family      = AF_INET;
+    sa.sin_addr.s_addr = htonl(INADDR_ANY);
+    sa.sin_port        = htons(tcp_port);
+    if ( bind(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 )
+    {
+        SYS_ERROR("Unable to bind to console port %d.", tcp_port);
+        close(fd);
+        return 0;
+    }
+
+    if ( listen(fd, 5) != 0 )
+    {
+        SYS_ERROR("Unable to listen on console port %d.", tcp_port);
+        close(fd);
+        return 0;
+    }
+
+    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
+         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
+    {
+        SYS_ERROR("Unable to set non-blocking status for console listener.");
+        close(fd);
+        return 0;
+    }
+
+    pinfo->con_fd     = fd;
+    pinfo->con_status = CONSTAT_LISTENING;
+    return 1;
+}
+
+/* Returns non-zero if console is connected on exit. */
+static int make_consock_connected(portinfo_t *pinfo)
+{
+    int fd, flags, sa_len;
+    struct linger linger;
+    struct sockaddr_in sa;
+
+    if ( pinfo->con_status == CONSTAT_CONNECTED )
+        return 1;
+
+    if ( pinfo->con_status == CONSTAT_CLOSED )
+        return 0;
+
+    if ( (fd = accept(pinfo->con_fd, (struct sockaddr *)&sa, &sa_len)) == -1 )
+        return 0;
+
+    linger.l_onoff = 0;
+    if ( setsockopt(fd, SOL_SOCKET, SO_LINGER, 
+                    &linger, sizeof(linger)) != 0 )
+    {
+        SYS_ERROR("Could not enable immediate socket death.");
+        close(fd);
+        return 0;
+    }
+
+    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
+         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
+    {
+        SYS_ERROR("Unable to set non-blocking status on socket.");
+        close(fd);
+        return 0;
+    }
+
+    (void)close(pinfo->con_fd);
+
+    pinfo->con_fd     = fd;
+    pinfo->con_status = CONSTAT_CONNECTED;
+    return 1;
+}
+
+
+static void make_consock_closed(portinfo_t *pinfo)
+{
+    if ( pinfo->con_status != CONSTAT_CLOSED )
+        (void)close(pinfo->con_fd);
+    pinfo->con_status = CONSTAT_CLOSED;
+}
+
+
+static void do_consock_read(portinfo_t *pinfo)
+{
+    char buf[1024];
+    int  idx, bytes, rc, was_empty = TX_EMPTY(pinfo);
+
+    while ( (rc = read(pinfo->con_fd, &buf, sizeof(buf))) > 0 )
+    {
+        idx = 0;
+        while ( (rc != 0) && !TX_FULL(pinfo) )
+        {
+            bytes = rc;
+            /* Clip copy to ring-buffer wrap. */
+            if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp)) )
+                bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp);
+            /* Clip copy to ring-buffer overflow. */
+            if ( bytes > (CONBUFSZ - (pinfo->txp - pinfo->txc)) )
+                bytes = CONBUFSZ - (pinfo->txp - pinfo->txc);
+            memcpy(&pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txp)],
+                   &buf[idx], bytes);
+            pinfo->txp += bytes;
+            idx        += bytes;
+            rc         -= bytes;
+        }
+    }
+
+    if ( (rc == 0) || (errno != EAGAIN) )
+    {
+        DPRINTF("Console client has disconnected.");
+        if ( !make_consock_listener(pinfo) )
+        {
+            ERROR("Could not revert console %d to listener status.",
+                  PORT(pinfo));
+            exit(1);
+        }
+    }
+
+    if ( was_empty && !TX_EMPTY(pinfo) )
+    {
+        /* There is now data to transmit to guest. Kickstart the pipeline. */
+        if ( process_evtchn_writes(pinfo) )
+            (void)xc_evtchn_send(xc_fd, PORT(pinfo));
+    }
+}
+
+static void do_consock_write(portinfo_t *pinfo)
+{
+    int bytes, rc;
+
+    while ( !RX_EMPTY(pinfo) )
+    {
+        /* Clip transfer to ring-buffer wrap. */
+        bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxc);
+        /* Clip transfer to ring-buffer overflow. */
+        if ( bytes > (pinfo->rxp - pinfo->rxc) )
+            bytes = pinfo->rxp - pinfo->rxc;
+        rc = write(pinfo->con_fd, 
+                   &pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxc)], 
+                   bytes);
+        if ( rc <= 0 )
+            return; /* Nothing to do. Errors cleaned up in reader code. */
+        pinfo->rxc += rc;
+    }
+}
+
+static int process_evtchn_reads(portinfo_t *pinfo)
+{
+    CONTROL_RING_IDX c;
+    control_if_t    *cif = pinfo->interface;
+    control_msg_t   *cmsg;
+    unsigned int     clen, idx, len, bytes;
+
+    for ( c = pinfo->tx_req_cons; 
+          (c != cif->tx_req_prod) && 
+              ((c-pinfo->tx_resp_prod) != CONTROL_RING_SIZE);
+          c++ )
+    {
+        cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+
+        if ( (clen = cmsg->length) > sizeof(cmsg->msg) )
+            clen = sizeof(cmsg->msg);
+
+        if ( (cmsg->cmd_type == CMD_CONSOLE) &&
+             (cmsg->cmd_subtype == CMD_CONSOLE_DATA) )
+        {
+            idx = 0;
+            len = cmsg->length;
+            while ( (len != 0) && !RX_FULL(pinfo) )
+            {
+                bytes = len;
+                /* Clip copy to ring-buffer wrap. */
+                if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp)) )
+                    bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp);
+                /* Clip copy to ring-buffer overflow. */
+                if ( bytes > (CONBUFSZ - (pinfo->rxp - pinfo->rxc)) )
+                    bytes = CONBUFSZ - (pinfo->rxp - pinfo->rxc);
+                memcpy(&pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxp)],
+                       &cmsg->msg[idx], bytes);
+                pinfo->rxp += bytes;
+                idx += bytes;
+                len -= bytes;
+            }
+        }
+
+        /* Prepare response. No payload; msg type and id same as request. */
+        cmsg->length = 0;
+    }
+
+    if ( c != pinfo->tx_req_cons )
+    {
+        /* Update private indexes. */
+        pinfo->tx_resp_prod = c;
+        pinfo->tx_req_cons  = c;
+        /* Queue responses and send a notification to the guest OS. */
+        cif->tx_resp_prod   = c;
+        return 1;
+    }
+
+    return 0;
+}
+
+static int process_evtchn_writes(portinfo_t *pinfo)
+{
+    CONTROL_RING_IDX p, rx_resp_prod;
+    control_if_t    *cif = pinfo->interface;
+    control_msg_t   *cmsg;
+    unsigned int     bytes;
+
+    /* Validate the rx-response producer, an dupdate our consumer if okay. */
+    rx_resp_prod = cif->rx_resp_prod;
+    if ( (pinfo->rx_resp_cons != rx_resp_prod) &&
+         ((pinfo->rx_req_prod - rx_resp_prod) <= CONTROL_RING_SIZE) &&
+         ((rx_resp_prod - pinfo->rx_resp_cons) <= CONTROL_RING_SIZE) )
+        pinfo->rx_resp_cons = cif->rx_resp_prod;
+
+    for ( p = pinfo->rx_req_prod;
+          (p-pinfo->rx_resp_cons) != CONTROL_RING_SIZE;
+          p++ )
+    {
+        if ( TX_EMPTY(pinfo) )
+            break;
+        cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
+        bytes = sizeof(cmsg->msg);
+        /* Clip transfer to ring-buffer wrap. */
+        if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc)) )
+            bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc);
+        /* Clip transfer to ring-buffer overflow. */
+        if ( bytes > (pinfo->txp - pinfo->txc) )
+            bytes = pinfo->txp - pinfo->txc;
+        cmsg->cmd_type    = CMD_CONSOLE;
+        cmsg->cmd_subtype = CMD_CONSOLE_DATA;
+        cmsg->id          = 0xaa;
+        cmsg->length      = bytes;
+        memcpy(&cmsg->msg[0], 
+               &pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txc)], 
+               bytes);
+        pinfo->txc += bytes;
+    }
+
+    if ( p != pinfo->rx_req_prod )
+    {
+        pinfo->rx_req_prod  = p;
+        cif->rx_req_prod    = p;
+        return 1;
+    }
+
+    return 0;
+}
index e0203fa69978321a1cb985a0f8662bacbab91d56..7c19b75bb3ebbab05b88c291e84cec220216918b 100644 (file)
@@ -32,7 +32,7 @@ clean: delete-links
        $(MAKE) -C common clean
        $(MAKE) -C net clean
        $(MAKE) -C drivers clean
-       $(MAKE) -C arch/$(ARCH) clean
+       $(MAKE) -C arch/$(TARGET_ARCH) clean
        rm -f *.o $(TARGET)* *~ core $(GENERATED_FILES)
 
 $(TARGET): delete-unfresh-files make-links $(GENERATED_FILES)
@@ -40,11 +40,11 @@ $(TARGET): delete-unfresh-files make-links $(GENERATED_FILES)
        $(MAKE) -C common
        $(MAKE) -C net
        $(MAKE) -C drivers
-       $(MAKE) -C arch/$(ARCH)
+       $(MAKE) -C arch/$(TARGET_ARCH)
 
 make-links: delete-links
-       ln -sf asm-$(ARCH) include/asm
-       ln -sf arch-$(ARCH) include/hypervisor-ifs/arch
+       ln -sf asm-$(TARGET_ARCH) include/asm
+       ln -sf arch-$(TARGET_ARCH) include/hypervisor-ifs/arch
 
 delete-links:
        rm -f include/asm include/hypervisor-ifs/arch
@@ -77,7 +77,7 @@ include/xeno/compile.h:
 
 SUBDIRS = arch common drivers net 
 TAGS: 
-       etags `find include/asm-$(ARCH) -name '*.h'`
+       etags `find include/asm-$(TARGET_ARCH) -name '*.h'`
        find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a
        find $(SUBDIRS) -name '*.[ch]' | xargs etags -a
 MAP:
index dc9c02993c71c16d600df5a9713878b8337b45e7..c96281116d9c463a0a1b84077b3e9560d490240b 100644 (file)
@@ -1,11 +1,11 @@
-ARCH    ?= i386
-ARCH    := $(ARCH:i%86=i386)
+COMPILE_ARCH := $(shell uname -m | sed -e s/i.86/i386/)
+TARGET_ARCH  ?= $(COMPILE_ARCH)
 
 TARGET  := $(BASEDIR)/xen
 HDRS    := $(wildcard $(BASEDIR)/include/xeno/*.h)
 HDRS    += $(wildcard $(BASEDIR)/include/scsi/*.h)
 HDRS    += $(wildcard $(BASEDIR)/include/hypervisor-ifs/*.h)
-HDRS    += $(wildcard $(BASEDIR)/include/asm-$(ARCH)/*.h)
+HDRS    += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/*.h)
 # compile.h is always regenerated, but other files shouldn't be rebuilt
 HDRS    := $(subst $(BASEDIR)/include/xeno/compile.h,,$(HDRS))
 
@@ -25,12 +25,12 @@ ALL_OBJS += $(BASEDIR)/drivers/cdrom/driver.o
 ALL_OBJS += $(BASEDIR)/drivers/ide/driver.o
 ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o
 ALL_OBJS += $(BASEDIR)/drivers/message/fusion/driver.o
-ALL_OBJS += $(BASEDIR)/arch/$(ARCH)/arch.o
+ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o
 
 HOSTCC     = gcc
 HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer 
 
-include $(BASEDIR)/arch/$(ARCH)/Rules.mk
+include $(BASEDIR)/arch/$(TARGET_ARCH)/Rules.mk
 
 %.o: %.c $(HDRS) Makefile
        $(CC) $(CFLAGS) -c $< -o $@